using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using LF.Domain.Services;

namespace LF.Application.Extend
{
    /// <summary>
    /// 自定义权限验证特性，支持层级权限验证
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
    public class LFAuthorizeAttribute : AuthorizeAttribute, IAsyncAuthorizationFilter
    {
        /// <summary>
        /// 权限名称（显示用）
        /// </summary>
        public string DisplayName { get; }

        /// <summary>
        /// 权限标识（验证用）
        /// </summary>
        public string PermissionCode { get; }

        /// <summary>
        /// 创建一个新的LFAuthorize特性
        /// </summary>
        /// <param name="displayName">权限显示名称</param>
        /// <param name="permissionCode">权限标识代码，例如：system:menu:list</param>
        public LFAuthorizeAttribute(string displayName, string permissionCode)
        {
            DisplayName = displayName;
            PermissionCode = permissionCode;
        }

        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            // 使用AllowAnonymous特性的方法跳过权限验证
            if (context.ActionDescriptor.EndpointMetadata.Any(m => m is AllowAnonymousAttribute))
            {
                return;
            }

            // 获取用户ID
            var userId = context.HttpContext.User.GetUserId();
            if (!userId.HasValue)
            {
                context.Result = new UnauthorizedResult();
                return;
            }

            // 获取用户名，检查是否是sysadmin
            var userName = context.HttpContext.User.Claims.FirstOrDefault(c => c.Type == "Name")?.Value;
            if (userName == "sysadmin")
            {
                // sysadmin用户直接跳过权限验证
                return;
            }

            // 获取IMenuManagerService服务来验证权限
            var menuManager = context.HttpContext.RequestServices.GetRequiredService<IMenuManagerService>();
            var userPermissions = menuManager.GetPermissionCodes(userId.Value);

            // 实现层级权限验证逻辑
            if (!HasPermission(userPermissions, PermissionCode))
            {
                context.Result = new ForbidResult();
                return;
            }

            await Task.CompletedTask;
        }

        /// <summary>
        /// 验证用户是否拥有指定权限或其上级权限
        /// </summary>
        private bool HasPermission(System.Collections.Generic.List<string> userPermissions, string requiredPermission)
        {
            // 拥有精确的权限
            if (userPermissions.Contains(requiredPermission))
                return true;

            // 检查是否拥有上级权限
            // 例如: 要求 system:menu:list, 用户拥有 system 或 system:menu 也可以通过
            var parts = requiredPermission.Split(':');
            for (int i = 1; i < parts.Length; i++)
            {
                var parentPerm = string.Join(":", parts.Take(i));
                if (userPermissions.Contains(parentPerm))
                    return true;
            }

            return false;
        }
    }
} 